package com.wlyuan.open.domain.source.dispatcher;

import com.wlyuan.core.exception.AssertUtils;
import com.wlyuan.open.OpenBaseSyncDTO;
import com.wlyuan.open.aspect.SourceDataEnd;
import com.wlyuan.open.domain.source.dispatcher.conversion.OpenDispatcherConverter;
import com.wlyuan.open.domain.source.service.*;
import com.wlyuan.open.dto.*;
import com.wlyuan.open.dto.tenant.OpenCompanyTenantSyncDTO;
import com.wlyuan.open.dto.tenant.OpenDriverTenantSyncDTO;
import com.wlyuan.open.dto.tenant.OpenTenantRelationSyncDTO;
import com.wlyuan.open.dto.top.OpenTopExtensionOrderSyncDTO;
import com.wlyuan.open.dto.transport.OpenTransportRelationSyncDTO;
import com.wlyuan.open.infrastructure.exception.SourceUnsupportedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * @author yuanzheng
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OpenSyncDispatcher {
    private final IOpenBasicService openBasicService;
    private final IOpenTenantService openTenantService;
    private final IOpenOrderService openOrderService;
    private final IOpenTransportService openTransportService;
    private final IOpenFinanceService openFinanceService;
    private final IOpenUserService openUserService;
    private final IOpenQuotationService quotationService;
    private final IOpenTopExtensionService topExtensionService;
    private final OpenDispatcherConverter openDispatcherConverter;
    private final Map<Class<?>, Function<OpenBaseSyncDTO, Long>> executors = new HashMap<>();

    @PostConstruct
    public void initialize() {
        executors.put(OpenGoodsSyncDTO.class, goods -> openBasicService.sync((OpenGoodsSyncDTO) goods));
        executors.put(OpenCarrierSyncDTO.class, carrier -> openBasicService.sync((OpenCarrierSyncDTO) carrier));
        executors.put(OpenConsigneeSyncDTO.class, consignee -> openBasicService.sync((OpenConsigneeSyncDTO) consignee));
        executors.put(OpenCustomerSyncDTO.class, customer -> openBasicService.sync((OpenCustomerSyncDTO) customer));
        executors.put(OpenCompanyTenantSyncDTO.class, tenant -> openTenantService.sync((OpenCompanyTenantSyncDTO) tenant));
        executors.put(OpenDriverTenantSyncDTO.class, tenant -> openTenantService.sync((OpenDriverTenantSyncDTO) tenant));
        executors.put(OpenDriverSyncDTO.class, driver -> openBasicService.sync((OpenDriverSyncDTO) driver));
        executors.put(OpenVehicleSyncDTO.class, vehicle -> openBasicService.sync((OpenVehicleSyncDTO) vehicle));
        executors.put(OpenOrderSyncDTO.class, order -> openOrderService.sync((OpenOrderSyncDTO) order));
        executors.put(OpenTransportSyncDTO.class, transport -> openTransportService.sync((OpenTransportSyncDTO) transport));
        executors.put(OpenContractSyncDTO.class, contract -> openBasicService.sync((OpenContractSyncDTO) contract));
        executors.put(OpenBillSyncDTO.class, finance -> openFinanceService.sync((OpenBillSyncDTO) finance));
        executors.put(OpenUserSyncDTO.class, user -> openUserService.sync((OpenUserSyncDTO) user));
        executors.put(OpenTenantRelationSyncDTO.class, tenantRelation -> openTenantService.sync((OpenTenantRelationSyncDTO) tenantRelation));
        executors.put(OpenCombineSyncDTO.class, combine -> openTransportService.sync((OpenCombineSyncDTO) combine));
        /*executors.put(OpenQuotationSyncDTO.class, quotation -> quotationService.sync((OpenQuotationSyncDTO) quotation));
        executors.put(OpenCombineQuotationSyncDTO.class, template -> quotationService.sync((OpenCombineQuotationSyncDTO) template));
        executors.put(OpenTemplateSyncDTO.class, template -> quotationService.sync((OpenTemplateSyncDTO) template));*/
        executors.put(OpenPaySyncDTO.class, pay -> openFinanceService.sync((OpenPaySyncDTO) pay));
        executors.put(OpenRelationSyncDTO.class, relation -> openBasicService.sync((OpenRelationSyncDTO) relation));
        executors.put(OpenTopExtensionOrderSyncDTO.class, top -> topExtensionService.sync((OpenTopExtensionOrderSyncDTO) top));
        executors.put(OpenTransportRelationSyncDTO.class, relation -> openTransportService.sync((OpenTransportRelationSyncDTO) relation));
    }

    @SourceDataEnd
    public <T extends OpenBaseSyncDTO> Long sync(T source) {
        //数据转换
        openDispatcherConverter.convert(source);
        var executor = executors.get(source.getClass());
        AssertUtils.assertNotNull(executor, new SourceUnsupportedException("同步服务未实现"), source);
        return executor.apply(source);
    }
}
